﻿// -----------------------------------------------------------------------
// <copyright file="UnityPageHandlerFactory.cs" company="Henadzi Sabaleuski.">
// Copyright (c) Henadzi Sabaleuski. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

namespace OCM.Enterprise.OCR.Utilities.Unity
{
	#region Usings

	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Reflection;
	using System.Security.Permissions;
	using System.Web;
	using System.Web.UI;
	using Microsoft.Practices.Unity;
	using Microsoft.Practices.Unity.Configuration;

	#endregion

	/// <summary>
	/// Implements the unity page handler factory.
	/// </summary>
	public class UnityPageHandlerFactory : PageHandlerFactory, IDisposable
	{
		#region Private Fields

		/// <summary>
		/// The unity container.
		/// </summary>
		private readonly UnityContainer unityContainer;

		/// <summary>
		/// Represents the disposing state of the object.
		/// </summary>
		private bool disposed = false;

		#endregion

		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="UnityPageHandlerFactory"/> class.
		/// </summary>
		[PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
		public UnityPageHandlerFactory()
		{
			this.unityContainer = new UnityContainer();
			this.unityContainer.LoadConfiguration();
		}

		#endregion

		#region Overrides

		/// <summary>
		/// Returns an instance of the <see cref="T:System.Web.IHttpHandler"/> interface to process the requested resource.
		/// </summary>
		/// <param name="context">An instance of the <see cref="T:System.Web.HttpContext"/> class that provides references to intrinsic server objects (for example, Request, Response, Session, and Server) used to service HTTP requests.</param>
		/// <param name="requestType">The HTTP data transfer method (GET or POST) that the client uses.</param>
		/// <param name="virtualPath">The virtual path to the requested resource.</param>
		/// <param name="path">The <see cref="P:System.Web.HttpRequest.PhysicalApplicationPath"/> property to the requested resource.</param>
		/// <returns>
		/// A new <see cref="T:System.Web.IHttpHandler"/> that processes the request; otherwise, null.
		/// </returns>
		[PermissionSet(SecurityAction.LinkDemand, Unrestricted = true)]
		public override IHttpHandler GetHandler(HttpContext context, string requestType, string virtualPath, string path)
		{
			IHttpHandler httpHandler = base.GetHandler(context, requestType, virtualPath, path);

			if (httpHandler != null)
			{
				IEnumerable<PropertyInfo> properties = httpHandler.GetType().GetProperties()
					.Where(m => m.GetCustomAttributes(typeof(DependencyAttribute), true).Any());

				foreach (PropertyInfo property in properties)
				{
					object value = this.unityContainer.Resolve(property.PropertyType);

					property.SetValue(httpHandler, value, null);
				}
			}

			return httpHandler;
		}

		#endregion

		#region IDisposable Members

		/// <summary>
		/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
		/// </summary>
		public void Dispose()
		{
			this.Dispose(true);

			GC.SuppressFinalize(this);
		}

		#endregion

		#region Private Implementation

		/// <summary>
		/// Releases unmanaged and - optionally - managed resources
		/// </summary>
		/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
		protected virtual void Dispose(bool disposing)
		{
			if (!this.disposed)
			{
				if (disposing)
				{
					if (this.unityContainer != null)
					{
						this.unityContainer.Dispose();
					}
				}
			}

			this.disposed = true;
		}

		#endregion
	}
}